﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using Win32SDK;
using System.Runtime.InteropServices;
using TaskSystemClient.SPM;
namespace TaskSystemClient
{
    public partial class BurnDownChart : Form
    {
        public BurnDownChart()
        {
            InitializeComponent();
        }

        public string CatalogType
        {
            get;
            set;
        }
        private string catalogName = "";
        public string CatalogName
        {
            get
            {
                return catalogName;
            }
            set
            {
                catalogName=value;
                if(catalogName==null)
                {
                    catalogName = "";
                }
            }
        }

        SPM.CatalogInformation catalogInformation = new SPM.CatalogInformation();
        void updateCatalogInformationToUI()
        {
            dtStartTime.Value = catalogInformation.StartDate;
            label_CatalogType.Text = catalogInformation.CatalogType;
            textBox_CatalogName.Text = catalogInformation.CatalogName;
            numericUpDown_DayCount.Minimum = 1;
            numericUpDown_DayCount.Maximum = 3650;
            numericUpDown_DayCount.Value = catalogInformation.DayCount;
        }
        void updateCatalogInformationFromUI()
        {
            catalogInformation.StartDate=dtStartTime.Value;
            //catalogInformation.CatalogType=label_CatalogType.Text;
            //catalogInformation.CatalogName=textBox_CatalogName.Text ;
            catalogInformation.DayCount=(int)numericUpDown_DayCount.Value;
        }

        private void BurnDownChart_Load(object sender, EventArgs e)
        {


            SPM.CatalogInformation[] catalogInformations=SPM.SP.GetCatalogInformation(CatalogType, CatalogName);
            if(catalogInformations.Length>0)
            {
                catalogInformation = new TaskSystemClient.SPM.CatalogInformation(catalogInformations[0]);
            }
            else
            {
                catalogInformation.CatalogType=CatalogType;
                catalogInformation.CatalogName = CatalogName;
                catalogInformation.StartDate = DateTime.Today;
                catalogInformation.DayCount = 365;
                //如果CatalogName能够分解成若干个数字，则以这些数字作为缺省的日期
                try
                {
                    List<string> catalogList = TaskTreeViewHelper.splitCatalog(CatalogName);
                    
                    if (catalogList.Count == 2)
                    {
                        int year = int.Parse(catalogList[0]);
                        int month = int.Parse(catalogList[1]);
                        if (year > 0 && month > 0)
                        {
                            catalogInformation.StartDate = new DateTime(year, month, 1);
                        }
                        catalogInformation.DayCount = 30;
                    }
                    else if (catalogList.Count == 1)
                    {
                        int year = int.Parse(catalogList[0]);
                        if (year > 0)
                        {
                            catalogInformation.StartDate = new DateTime(year, 1, 1);
                        }
                        catalogInformation.DayCount = 365;
                    }
                    else if (catalogList.Count >= 3)
                    {
                        int year = int.Parse(catalogList[0]);
                        int month = int.Parse(catalogList[1]);
                        int day = int.Parse(catalogList[2]);
                        if (year > 0 && month > 0 && day > 0)
                        {
                            catalogInformation.StartDate = new DateTime(year, month, day);
                        }
                        catalogInformation.DayCount = 7;
                    }
                }
                catch (System.Exception )
                {
                	
                }
                
                catalogInformation.IsMilestone = 0;
            }

            updateCatalogInformationToUI();


            //;根据当前用户的名字决定一个缺省的分组
            UserGroup user = UserGroupManager.Instance[Global<MainForm>.Instance.UserName];
            string groupName = "";
            if (user != null)
            {
                groupName=user.Group1;
            }
            int index = 0;
            foreach (string v in comboBox_GroupName.Items)
            {
                if(v==groupName)
                {
                    comboBox_GroupName.SelectedIndex=index;
                    break;
                }
                index++;
            }

            UpdateChart1();
        }

        private void UpdateChart1()
        {
            Chart chart = chart1;
            chart.Titles.Clear();
            chart.Series.Clear();
            chart.Legends.Clear();

            SPM.BurnDownData[] datas = SPM.SP.GetBurnDownData(catalogInformation.CatalogType, catalogInformation.CatalogName, catalogInformation.StartDate, catalogInformation.DayCount,comboBox_GroupName.Text);

            Title t = chart.Titles.Add("时间");
            t.Text = string.Format("燃尽图-{0}", catalogInformation.CatalogName);

            Series s1 = null, s2 = null, s3 = null, s4 = null, s5 = null, s6 = null;

            s1 = chart.Series.Add("今日新增");
            s2 = chart.Series.Add("今日完成");
            s3 = chart.Series.Add("今日待查");
            s4 = chart.Series.Add("累计新增");
            s5 = chart.Series.Add("累计完成");
            s6 = chart.Series.Add("剩余工作");

            s1.Color = System.Drawing.Color.Red;
            s2.Color = System.Drawing.Color.Green;
            s3.Color = System.Drawing.Color.Blue;
            s4.Color = System.Drawing.Color.DarkRed;
            s5.Color = System.Drawing.Color.DarkBlue;
            s6.Color = System.Drawing.Color.Gold;

            if (datas.Length>60)
            {
                s1.ChartType = SeriesChartType.FastLine;
                s2.ChartType = SeriesChartType.FastLine;
                s3.ChartType = SeriesChartType.FastLine;
                s4.ChartType = SeriesChartType.FastLine;
                s5.ChartType = SeriesChartType.FastLine;
                s6.ChartType = SeriesChartType.FastLine;

                s1.BorderWidth = 1;
                s2.BorderWidth = 1;
                s3.BorderWidth = 1;
                s4.BorderWidth = 1;
                s5.BorderWidth = 1;
                s6.BorderWidth = 3;
            }
            else
            {
                // Set point width of the series
                s1["PointWidth"] = "0.8"; //0.8,0.4

                // Set drawing style
                //"Default", "Emboss", "Cylinder","Wedge","LightToDark"
                s1["DrawingStyle"] = "Emboss";

                s2["PointWidth"] = "0.8"; //0.8,0.4
                s2["DrawingStyle"] = "Emboss";

                s3["PointWidth"] = "0.8"; //0.8,0.4
                s3["DrawingStyle"] = "Emboss";


                s4["DrawingStyle"] = "Emboss";
                s5["DrawingStyle"] = "Emboss";
                s6["DrawingStyle"] = "Emboss";

                s4.ChartType = SeriesChartType.Line;
                s5.ChartType = SeriesChartType.Line;
                s6.ChartType = SeriesChartType.Line;

                s1.ChartType = SeriesChartType.Column;
                s2.ChartType = SeriesChartType.Column;
                s3.ChartType = SeriesChartType.Column;

                s4.MarkerStyle = MarkerStyle.Diamond;
                s4.MarkerStep = (int)(datas.Length / 15) < 1 ? 1 : (int)(datas.Length / 15);
                s4.MarkerSize = 6;
                s4.BorderWidth = 2;
                s4.Label = "";

                s5.MarkerStyle = MarkerStyle.Square;
                s5.MarkerStep = (int)(datas.Length / 15) < 1 ? 1 : (int)(datas.Length / 15);
                s5.MarkerSize = 6;
                s5.BorderWidth = 2;

                s6.MarkerStyle = MarkerStyle.Circle;
                s6.MarkerStep = (int)(datas.Length / 15) < 1 ? 1 : (int)(datas.Length / 15);
                s6.MarkerSize = 12;
                s6.BorderWidth = 3;

                s1.ShadowOffset = 3;
                s2.ShadowOffset = 3;
                s3.ShadowOffset = 3;
                s4.ShadowOffset = 3;
                s5.ShadowOffset = 3;
                s6.ShadowOffset = 3;


                s1.IsValueShownAsLabel = false;
                s2.IsValueShownAsLabel = false;
                s3.IsValueShownAsLabel = false;
                s4.IsValueShownAsLabel = false;
                s5.IsValueShownAsLabel = false;
                s6.IsValueShownAsLabel = false;

                s1.ToolTip = "今日新增: #VAL";
                s2.ToolTip = "今日完成: #VAL";
                s3.ToolTip = "今日待查: #VAL";
                s4.ToolTip = "累计新增: #VAL";
                s5.ToolTip = "累计完成(含待查): #VAL";
                s6.ToolTip = "剩余数量: #VAL";
            }
 

            Legend l1 = chart.Legends.Add("今日新增");
            Legend l2 = chart.Legends.Add("今日完成");
            Legend l3 = chart.Legends.Add("今日待查");
            Legend l4 = chart.Legends.Add("累计新增");
            Legend l5 = chart.Legends.Add("累计完成");
            Legend l6 = chart.Legends.Add("剩余工作");

            List<string> names = new List<string>();
            List<int> data1 = new List<int>();
            List<int> data2 = new List<int>();
            List<int> data3 = new List<int>();
            List<int> data4 = new List<int>();
            List<int> data5 = new List<int>();
            List<int> data6 = new List<int>();

            int new_per_day = 0;
            int new_to_today = 0;
            int done_per_day = 0;
            int done_to_today = 0;
            int checking_per_day = 0;
            for (int j = 0; j < datas.Length; ++j)
            {
                SPM.BurnDownData data = datas[j];
                new_per_day = data.NewCount;
                new_to_today += new_per_day;
                done_per_day = data.DoneCount;
                checking_per_day = data.CheckingCount;
                done_to_today += done_per_day;
                done_to_today += checking_per_day;
                data1.Add(new_per_day);
                data2.Add(checking_per_day);
                data3.Add(done_per_day);
                data4.Add(new_to_today);
                data5.Add(done_to_today);
                data6.Add(new_to_today - done_to_today);
                names.Add(data.Date);
            }

            s1.Points.DataBindXY(names, data1);
            s2.Points.DataBindXY(names, data2);
            s3.Points.DataBindXY(names, data3);
            s4.Points.DataBindXY(names, data4);
            s5.Points.DataBindXY(names, data5);
            s6.Points.DataBindXY(names, data6);
        }



        class WorkData
        {
            public string GroupName = "";
            public string TaskUser="";
            public int NewCount=0;
            public int DoneCount=0;
            public int CheckingCount=0;
        };

        private void UpdateChart2()
        {
            Chart chart = chart2;
            chart.Titles.Clear();
            chart.Series.Clear();
            chart.Legends.Clear();

            chart.ChartAreas[0].AxisX.MajorTickMark.Interval = 1;
            chart.ChartAreas[0].AxisX.Interval = 1;
            SPM.UserWorkData[] datas = SPM.SP.GetUserWorkData(catalogInformation.CatalogType, catalogInformation.CatalogName, catalogInformation.StartDate, catalogInformation.DayCount,comboBox_GroupName.Text);

            List<WorkData> workDatas = new List<WorkData>();
            for (int j = 0; j < datas.Length; ++j)
            {
                WorkData wd = null;
                foreach (WorkData w in workDatas)
                {
                    if (string.Compare(w.TaskUser, datas[j].TaskUser) == 0)
                    {
                        wd = w;
                        break;
                    }
                }
                if (wd == null)
                {
                    wd = new WorkData();
                    wd.GroupName = datas[j].GroupName;
                    wd.TaskUser = datas[j].TaskUser;
                    workDatas.Add(wd);
                }
                if (string.Compare(datas[j].TaskState, "checking") == 0)
                {
                    wd.CheckingCount += datas[j].Count;
                    wd.NewCount += datas[j].Count;
                }
                else if (string.Compare(datas[j].TaskState, "done") == 0)
                {
                    wd.DoneCount += datas[j].Count;
                    wd.NewCount += datas[j].Count;
                }
                else
                {
                    wd.NewCount += datas[j].Count;
                }
            }

            workDatas.Sort(
                delegate(WorkData w1, WorkData w2)
                {
                    int v = w1.GroupName.CompareTo(w2.GroupName);
                    if (v != 0)
                    {
                        return v;
                    }
                    int v1 = w1.CheckingCount + w1.DoneCount;
                    int v2 = w2.CheckingCount + w2.DoneCount;
                    if (v1 < v2) return 1;
                    if (v1 > v2) return -1;
                    return w1.TaskUser.CompareTo(w2.TaskUser);
                }
                );


            Title t = chart.Titles.Add("时间");
            t.Text = string.Format("每人工作-{0}", catalogInformation.CatalogName);

            Series s1 = null, s2 = null,s3=null;

            s1 = chart.Series.Add("所有任务");
            s2 = chart.Series.Add("待查任务");
            s3 = chart.Series.Add("完成任务");

            s1.Color = System.Drawing.Color.Red;
            s2.Color = System.Drawing.Color.Blue;
            s3.Color = System.Drawing.Color.Green;

            if (workDatas.Count > 60)
            {
                s1.ChartType = SeriesChartType.FastLine;
                s2.ChartType = SeriesChartType.FastLine;
                s3.ChartType = SeriesChartType.FastLine;

                s1.BorderWidth = 1;
                s2.BorderWidth = 1;
                s3.BorderWidth = 1;
            }
            else
            {
                // Set point width of the series
                s1["PointWidth"] = "0.8"; //0.8,0.4

                // Set drawing style
                //"Default", "Emboss", "Cylinder","Wedge","LightToDark"
                s1["DrawingStyle"] = "Emboss";

                s2["PointWidth"] = "0.8"; //0.8,0.4
                s2["DrawingStyle"] = "Emboss";

                s3["PointWidth"] = "0.8"; //0.8,0.4
                s3["DrawingStyle"] = "Emboss";

                s1.ChartType = SeriesChartType.Column;
                s2.ChartType = SeriesChartType.StackedColumn;
                s3.ChartType = SeriesChartType.StackedColumn;

                s1.ShadowOffset = 3;
                s2.ShadowOffset = 3;
                s3.ShadowOffset = 3;


                s1.IsValueShownAsLabel = false;
                s2.IsValueShownAsLabel = false;
                s3.IsValueShownAsLabel = false;

                s1.ToolTip = "所有任务: #VAL";
                s2.ToolTip = "待查任务: #VAL";
                s3.ToolTip = "完成任务: #VAL";

            }


            Legend l1 = chart.Legends.Add("所有任务");
            Legend l2 = chart.Legends.Add("待查任务");
            Legend l3 = chart.Legends.Add("完成任务");

            List<string> names = new List<string>();
            List<int> data1 = new List<int>();
            List<int> data2 = new List<int>();
            List<int> data3 = new List<int>();



            foreach(WorkData data in workDatas)
            {
                data1.Add(data.NewCount);
                data2.Add(data.DoneCount);
                data3.Add(data.CheckingCount);
                names.Add(data.TaskUser);
            }
            s1.Points.DataBindXY(names, data1);
            s2.Points.DataBindXY(names, data2);
            s3.Points.DataBindXY(names, data3);
            s1.IsXValueIndexed = true;
        }

        private void OnUpdateTime(object sender, EventArgs e)
        {
            //不能在这里调用 updateCatalogInformationFromUI ,会产生循环
        }

        private void numericUpDown_DayCount_ValueChanged(object sender, EventArgs e)
        {
            //不能在这里调用 updateCatalogInformationFromUI ,会产生循环
        }

        private void button_Update_Click(object sender, EventArgs e)
        {
            updateCatalogInformationFromUI();
            doUpdateChart();
            SPM.SP.UpdateCatalogInformation(catalogInformation);
        }

        private void dtStartTime_DropDown(object sender, EventArgs e)
        {
            //DateTimePicker picker = sender as DateTimePicker;
            //Rectangle rect = picker.Bounds;
            //int lParam = ((rect.Height / 2) << 16) | (rect.Width - 5);
            //User32.PostMessage(new HandleRef(picker, picker.Handle), Constants.WM_LBUTTONDOWN, Constants.MK_LBUTTON, lParam);
            //User32.PostMessage(new HandleRef(picker, picker.Handle), Constants.WM_LBUTTONUP, Constants.MK_LBUTTON, lParam);
            //User32.ReleaseCapture();
        }

        private void button_SavePNG_Click(object sender, EventArgs e)
        {
            SaveToBmp(GetCurrentChart());
        }

        private void SaveToBmp(Chart chart)
        {
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.FileName = catalogInformation.CatalogName + ".png";
            // Sets the current file name filter string, which determines 
            // the choices that appear in the "Save as file type" or 
            // "Files of type" box in the dialog box.
            saveFileDialog1.Filter = "Bitmap (*.bmp)|*.bmp|JPEG (*.jpg)|*.jpg|EMF (*.emf)|*.emf|PNG (*.png)|*.png|GIF (*.gif)|*.gif|TIFF (*.tif)|*.tif";
            saveFileDialog1.FilterIndex = 4;
            saveFileDialog1.RestoreDirectory = true;

            // Set image file format
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                ChartImageFormat format = ChartImageFormat.Bmp;

                if (saveFileDialog1.FileName.EndsWith("bmp"))
                {
                    format = ChartImageFormat.Bmp;
                }
                else if (saveFileDialog1.FileName.EndsWith("jpg"))
                {
                    format = ChartImageFormat.Jpeg;
                }
                else if (saveFileDialog1.FileName.EndsWith("emf"))
                {
                    format = ChartImageFormat.Emf;
                }
                else if (saveFileDialog1.FileName.EndsWith("gif"))
                {
                    format = ChartImageFormat.Gif;
                }
                else if (saveFileDialog1.FileName.EndsWith("png"))
                {
                    format = ChartImageFormat.Png;
                }
                else if (saveFileDialog1.FileName.EndsWith("tif"))
                {
                    format = ChartImageFormat.Tiff;
                }

                // Save image
                chart.SaveImage(saveFileDialog1.FileName, format);
            }
        }

        private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
        {
            // Add custom painting only to the series with the name "Series2"
            if(e.ChartElement is Series )
            {
                Series series = (Series) e.ChartElement;
                if (series.Name == "剩余工作")
                {
                    if(series.Points.Count>120)
                    {
                        return;
                    }
                    // Load bitmap from file 
                    System.Drawing.Image bitmap = Bitmap.FromFile("E:\\work\\work\\trunk\\client_output\\EditorData\\resources\\Fire.png");

                    // Set Red color as transparent
                    System.Drawing.Imaging.ImageAttributes attrib = new System.Drawing.Imaging.ImageAttributes();
                    attrib.SetColorKey(Color.White, Color.White, System.Drawing.Imaging.ColorAdjustType.Default);

                    // Find data point with maximum Y value
                    int x_index = 1;
                    foreach (DataPoint dataPoint in series.Points)
                    {
                        if(series.Points.Count>8)
                        {
                            if(x_index!=1 && x_index!=series.Points.Count)
                            {
                                if (x_index % (int)(series.Points.Count/8.0+0.99)!=0)
                                {
                                    x_index++;
                                    continue;
                                }
                            }
                        }
                        // Calculates marker position depending on the data point X and Y values
                        RectangleF imagePosition = RectangleF.Empty;
                        imagePosition.X = (float)e.ChartGraphics.GetPositionFromAxis(
                            "ChartArea1", AxisName.X, x_index);
                        imagePosition.Y = (float)e.ChartGraphics.GetPositionFromAxis(
                            "ChartArea1", AxisName.Y, dataPoint.YValues[0]);
                        imagePosition = e.ChartGraphics.GetAbsoluteRectangle(imagePosition);
                        imagePosition.Width = bitmap.Width;
                        imagePosition.Height = bitmap.Height;
                        imagePosition.Y -= bitmap.Height;
                        imagePosition.X -= bitmap.Width/2;
                        // Draw image

                        e.ChartGraphics.Graphics.DrawImage(bitmap,
                            Rectangle.Round(imagePosition),
                            0, 0, bitmap.Width, bitmap.Height,
                            GraphicsUnit.Pixel
                            ,attrib
                            );
                        x_index++;
                    }


                    // Dispose image object
                    bitmap.Dispose();
                }
            }
        }

        Chart GetCurrentChart()
        {
            if (tabControl1.SelectedIndex == 0)
            {
                return chart1;
            }
            else
            {
                return chart2;
            }
        }
        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            doUpdateChart();
        }
        void doUpdateChart()
        {
            if (tabControl1.SelectedIndex == 0)
            {
                UpdateChart1();
            }
            else
            {
                UpdateChart2();
            }
        }

        private void comboBox_GroupName_SelectionChangeCommitted(object sender, EventArgs e)
        {
            
        }

        private void comboBox_GroupName_TextChanged(object sender, EventArgs e)
        {
            
        }

        private void comboBox_GroupName_TextUpdate(object sender, EventArgs e)
        {

        }

        private void comboBox_GroupName_SelectedIndexChanged(object sender, EventArgs e)
        {
            doUpdateChart();
        }
    }
}
